﻿#include "stdafx.h"
#include "GameInfo.h"
#include "CaptureTool.h"
#include <algorithm>
#include "Routine/Common/IRoutine.h"
#include "Team_Raid_Info.h"
#include "Routine/Common/RoutineAction.h"


GameInfo::GameInfo() {
	player_info = std::make_shared<Team_Raid_Info>();
	target_info = std::make_shared<Team_Raid_Info>();
}

GameInfo::~GameInfo() {
}

GameInfo game_info;

GameInfo & GameInfo::inst() {
	return game_info;
}

void GameInfo::Init() {
	InitSpellName();
	InitProperty();
	InitHealSpellConfigConfig();
	InitSpellCostManaConfig();
	InitSpellAddAstralPowerConfig();
}

bool GameInfo::ObtainInfo() {
	SetShowInfo(false);
	if (!ObtainPlayerHp()) {
		return false;
	}
	if (!ObtainPlayerMana()) {
		return false;
	}
	if (!ObtainClassInfo()) {
		return false;
	}
	if (!ObtainPlayerOtherInfo()) {
		return false;
	}
	ObtainTargetHp();
	ObtainPetHp();
	ObtainRuneInfo();
	ObtainPlayerBuff();
	ObtainTargetDebuff();
	ObtainActionBarInfo();
	ObtainTeamAndRaid();
	SetShowInfo(true);
	return true;
}

void GameInfo::InitSpellName() {
	// 把所有db的 SpellDef 拷贝 map_spell_config 中
	if (DbTool::inst().LoadAllSpellDef()) {
		auto & vec_config = DbTool::inst().GetSpellConfig();
		for (auto & ptr : vec_config) {
			if (map_spell_config_.find(ptr->spell_id) == map_spell_config_.end()) {
				map_spell_config_[ptr->spell_id] = *ptr;
			}
		}
	}
}

void GameInfo::InitProperty()
{
	if (DbTool::inst().LoadPropertyDef())
	{
		GetRoutineConfig().UpdateByDB();
		SaveAllPropertyDef();
	}
}

void GameInfo::SaveAllPropertyDef()
{
	for (auto& config : GetRoutineConfig().ClassConfig)
	{
		auto& vec_property = config.second->vec_property;
		for (auto& prop : vec_property)
		{
			DbTool::inst().UpdateProperty(prop);
		}
	}
}

Property* GameInfo::FindProperty(InterfaceClassConfig& config, std::string& name)
{
	Property* ret = nullptr;
	if (config.CheckCache())
	{
		auto it = config.map_cache_property.find(name);
		if (it != config.map_cache_property.end())
		{
			ret = it->second;
		}
	}
	return ret;
}

bool GameInfo::ConditionSatisfy(Property& prop, Team_Raid_Info& target)
{
	bool satisfy = false;
	switch (prop.condition)
	{
	case PC_if_hp_less_then_value:
		if (target.player_hp < std::any_cast<int>(prop.value2))
		{
			satisfy = true;
		}
		break;
	case PC_if_hp_percent_less_then_value:
		if (target.HpPecent() < std::any_cast<double>(prop.value))
		{
			satisfy = true;
		}
		break;
	default:
		break;
	}
	return satisfy;
}

PreviousMgr& GameInfo::prev()
{
	return prev_;
}

ShipFormMgr& GameInfo::shiftform()
{
	return shipform_;
}

bool GameInfo::Ap_Check(SpellID speed_id)
{
	if (player_mana + GetSpellAp(speed_id) <= player_mana_max)
	{
		return true;
	}
	return false;
}

SpellTargetMgr& GameInfo::SpellTarget()
{
	return spell_target_;
}

bool GameInfo::SatisfySpellCondition(std::string& name, SpecializationID speci_id, Team_Raid_Info& target)
{
	IClassConfigPtr& config = routine_config.ClassConfig[speci_id];
	Property* prop = FindProperty(*config, name);
	if (prop)
	{
		return ConditionSatisfy(*prop, target);
	}
	return false;
}

TalentMgr& GameInfo::talent()
{
	return talent_mgr;
}

BuffMgr& GameInfo::buff()
{
	return buff_mgr;
}

VariableMgr& GameInfo::Variable()
{
	return variable_;
}

void GameInfo::ObtainTeamAndRaid() {
	vec_team_and_raid_.clear();
	if (this->IsInParty() || this->IsInRaid())
	{
		int nBegin_Line = 15;
		for (int i = 1; i <= 40; i++) {
			std::shared_ptr<Team_Raid_Info> ptr_info = std::make_shared<Team_Raid_Info>();
			Team_Raid_Info &info = *ptr_info;
			info.index = i;
			int line = nBegin_Line + i - 1;
			int no_user1;
			int no_user2;
			CaptureTool::inst().GetValueFromImg(0, line, info.index, info.UnitIsTarget, info.isRaidOrParty, no_user2);
			if (info.isRaidOrParty == 2 || info.isRaidOrParty == 3)
			{
				info.player_hp = CaptureTool::inst().GetValueFromImg(1, line);
				info.player_hp_max = CaptureTool::inst().GetValueFromImg(2, line);

				int dead_or_ghost_role = 0;
				CaptureTool::inst().GetValueFromImg(3, line, dead_or_ghost_role, info.can_attack, info.can_assist, no_user2);
				info.is_dead_or_ghost = dead_or_ghost_role % 10;
				info.unit_role = dead_or_ghost_role / 10;

				info.x1 = CaptureTool::inst().GetValueFromImg(4, line);
				info.y1 = CaptureTool::inst().GetValueFromImg(5, line);
				info.aura_count = CaptureTool::inst().GetValueFromImg(6, line);
				info.MakeTargetName();
				for (int i = 0; i < info.aura_count; i++)
				{
					BuffOrDebuff aura;
					aura.spell_id = CaptureTool::inst().GetValueFromImg(6 + i * 2 + 1, line);
					int buf_msg;
					CaptureTool::inst().GetValueFromImg(6 + i * 2 + 2, line, aura.duration, aura.stack, buf_msg, no_user1);
					aura.cast_by_player = buf_msg / 100;
					aura.buff_or_debuff = buf_msg % 100;

					if (aura.buff_or_debuff == 1)
					{
						info.buffs.push_back(aura);
					}
					else
					{
						info.debuffs.push_back(aura);
					}
				}
				vec_team_and_raid_.push_back(ptr_info);
			}
		}
	}
}

void GameInfo::ObtainRuneInfo() {
	// 获得DK的符文准备好的数量
	SetRuneReadyCount(CaptureTool::inst().GetValueFromImg(4, 3));
	// 获得6个符文的CD
	vec_rune_.resize(7);
	for (int i = 1; i <= 6; i++) {
		int no_use1;
		int no_use2;
		auto & rune = vec_rune_[i];
		CaptureTool::inst().GetValueFromImg(i + 4, 3, rune.rune_rest_time, rune.rune_slot_amount, no_use1, no_use2);
	}
}

size_t GameInfo::GetActionCount() {
	return vec_action_.size();
}

bool GameInfo::ObtainPlayerOtherInfo() {
	int no_use1, no_use2, no_use3;
	CaptureTool::inst().GetValueFromImg(8, 1, player_is_channel, player_is_casting, no_use1, no_use2);
	int canInterrupt = CaptureTool::inst().GetValueFromImg(9, 1);
	SetTargetSpellCanInterupt(canInterrupt);
	int isInParty = 0;
	int PartyNum = 0;
	CaptureTool::inst().GetValueFromImg(10, 1, isInParty, PartyNum, no_use1, no_use2);
	SetPartyInfo(isInParty, PartyNum);
	int isInRaid = 0;
	int RaidNum = 0;
	CaptureTool::inst().GetValueFromImg(11, 1, isInRaid, RaidNum, no_use1, no_use2);
	SetRaidInfo(isInRaid, RaidNum);
	SetPlayerSpecializationID(CaptureTool::inst().GetValueFromImg(12, 1));
	int is_player_is_target = -1;
	CaptureTool::inst().GetValueFromImg(13, 1, is_player_is_target, player_info->unit_role, player_info->is_dead_or_ghost, no_use3);
	CaptureTool::inst().GetValueFromImg(14, 1, talent_count, no_use1, no_use2, no_use3);
	if (talent_count)
	{
		vec_talent.resize(talent_count);
		talent_mgr.map_talent_.clear();
		for (int i = 0; i < talent_count; i++)
		{
			auto& talent = vec_talent[i];
			talent.TalentID = CaptureTool::inst().GetValueFromImg(14 + i * 3 + 1, 1);
			talent.column = CaptureTool::inst().GetValueFromImg(14 + i * 3 + 2, 1);
			int talent_id = CaptureTool::inst().GetValueFromImg(14 + i * 3 + 3, 1);
			talent.spell_id = (SpellID)talent_id;
			talent.row = i;
			SpellConfig& config = GameInfo::inst().GetSpellConfigBySpellID(talent.spell_id);
			TalentData talent_data{ true };
			talent_mgr.map_talent_[(kTalentID)talent.spell_id] = talent_data;
		}
	}
	player_info->y1 = CaptureTool::inst().GetValueFromImg(36, 1);
	player_info->x1 = CaptureTool::inst().GetValueFromImg(37, 1);

	mana_power_type = CaptureTool::inst().GetValueFromImg(38, 1);
	power_type = CaptureTool::inst().GetValueFromImg(39, 1);
	power_cur = CaptureTool::inst().GetValueFromImg(40, 1);
	power_max = CaptureTool::inst().GetValueFromImg(41, 1);
	nFormID = CaptureTool::inst().GetValueFromImg(42, 1);
	ConRoSpellID = CaptureTool::inst().GetValueFromImg(43, 1);
	RoutineAction::SetConRoSpellID(ConRoSpellID);
	if (nFormID == shipform_.GetWaitFormID())
	{
		shipform_.ClearWait();
	}
	if (is_player_is_target == 1)
	{
		SetIsPlayerIsTarget(true);
	}
	else
	{
		SetIsPlayerIsTarget(false);
	}
	if (canInterrupt > 1 || canInterrupt < 0) {
		return false;
	}
	if (GetPlayerSpecializationID() <= 0 || GetPlayerSpecializationID() >= 600) {
		return false;
	}
	if (talent_count <= 0 || talent_count > 7)
	{
		return false;
	}
	return true;
}

void GameInfo::ObtainPetHp() {
	// 获得宠物的血量
	has_pet_ui = CaptureTool::inst().GetValueFromImg(1, 3);
	SetPetHp(CaptureTool::inst().GetValueFromImg(2, 3));
	pet_hp_max = CaptureTool::inst().GetValueFromImg(3, 3);
}

void GameInfo::ObtainTargetDebuff() {
	// 获得当前目标的所有debuff
	target_info->buffs.clear();
	target_info->debuffs.clear();
	target_info->aura_count = CaptureTool::inst().GetValueFromImg(6, 6);
	for (int i = 0; i < target_info->aura_count; i++) {
		BuffOrDebuff aura;
		aura.spell_id = CaptureTool::inst().GetValueFromImg(6 + i * 2 + 1, 6);
		int a, buf_msg;
		CaptureTool::inst().GetValueFromImg(6 + i * 2 + 2, 6, aura.duration, aura.stack, buf_msg, a);
		aura.cast_by_player = buf_msg / 100;
		aura.buff_or_debuff = buf_msg % 100;

		if (aura.buff_or_debuff == 1)
		{
			target_info->buffs.push_back(aura);
		}
		else
		{
			target_info->debuffs.push_back(aura);
		}
	}
	// vector to map
	target_info->aura_buffs_to_map();
}

void GameInfo::ObtainPlayerBuff() {
	// 获得当前玩家的所有buff
	player_info->buffs.clear();
	player_info->debuffs.clear();
	player_info->aura_count = CaptureTool::inst().GetValueFromImg(6, 5);
	for (int i = 0; i < player_info->aura_count; i++) {
		BuffOrDebuff aura;
		aura.spell_id = CaptureTool::inst().GetValueFromImg(6 + i * 2 + 1, 5);
		int a, buf_msg;
		CaptureTool::inst().GetValueFromImg(6 + i * 2 + 2, 5, aura.duration, aura.stack, buf_msg, a);
		aura.cast_by_player = buf_msg / 100;
		aura.buff_or_debuff = buf_msg % 100;
		if (aura.buff_or_debuff == 1)
		{
			player_info->buffs.push_back(aura);
		}
		else
		{
			player_info->debuffs.push_back(aura);
		}
	}
	// vector to map
	player_info->aura_buffs_to_map();
}

void GameInfo::ObtainActionBarInfo() {
	// 获得法术公共cd
	{
		ActionSt action;
		int no_use;
		CaptureTool::inst().GetValueFromImg(0, 11, action.in_range, action.cool_down, action.type, no_use);
		SetGlobalCD(action.cool_down);
	}
	// 获得动作条的所有信息
	{
		vec_action_.clear();
		int line = 11;
		ObtainActionBar(line);
		for (int i = 12; i <= 14; i++) {
			ObtainActionBar(i);
		}
	}
	//  把动作条vector转为map
	map_action_.clear();
	for (int iAction = 0; iAction < 48; iAction++) {
		auto & action = vec_action_[iAction];
		if (action.spell_id != 0)
		{
			map_action_[action.spell_id] = action;
		}
	}
}

void GameInfo::ObtainActionBar(int line) {
	for (int iAction = 0; iAction < 12; iAction++) {
		vec_action_.push_back(ActionSt());
		auto & action = vec_action_[vec_action_.size() - 1];
		int no_use;
		CaptureTool::inst().GetValueFromImg(1 + iAction * 3, line, action.in_range, action.cool_down, action.type, no_use);
		action.spell_id = CaptureTool::inst().GetValueFromImg(2 + iAction * 3, line);
		CaptureTool::inst().GetValueFromImg(3 + iAction * 3, line, action.spell_charge_curr, action.spell_charge_max, action.spell_charge_left, no_use);
		if (action.spell_id == 16777215 || action.type == 255 || action.type == 0) {
			action.spell_id = 0;
		}
		int key_index = iAction + 1;
		if (line == 12) {
			key_index += 48;
		}
		if (line == 13)
		{
			key_index += 24;
		}
		if (line == 14)
		{
			key_index += 60;
		}
		action.key_index = key_index;
	}
}

bool GameInfo::ObtainClassInfo() {
	// 获得当前玩家职业
	int r = 0;
	int g = 0;
	int b = 0;
	int a = 0;
	CaptureTool::inst().GetValueFromImg(7, 1, r, g, b, a);
	SetPlayerClass(r);
	SetPlayerSpec(g);
	if (r >= 1 && r <= 12) {
		return true;
	}
	return false;
}

bool GameInfo::ObtainPlayerMana() {
	target_is_enemy = CaptureTool::inst().GetValueFromImg(3, 1);
	in_battle = CaptureTool::inst().GetValueFromImg(4, 1);
	// 获得玩家当前能量
	SetPlayerMana(CaptureTool::inst().GetValueFromImg(5, 1));
	SetPlayerManaMax(CaptureTool::inst().GetValueFromImg(6, 1));
	if (GetPlayerMana() >= 0 && GetPlayerManaMax() > 10 && GetPlayerManaMax() >= GetPlayerMana()) {
	}
	else {
		return false;
	}
	return true;
}

void GameInfo::ObtainTargetHp() {
	// 获得当前目标的血量

	Team_Raid_Info &info = *target_info;
	info.index = -2;
	int line = 2;
	int no_user2;
	info.player_hp = CaptureTool::inst().GetValueFromImg(1, line);
	info.player_hp_max = CaptureTool::inst().GetValueFromImg(2, line);
	int dead_or_ghost_role = 0;
	CaptureTool::inst().GetValueFromImg(3, line, dead_or_ghost_role, info.can_attack, info.can_assist, no_user2);
	info.is_dead_or_ghost = dead_or_ghost_role % 10;
	info.unit_role = dead_or_ghost_role / 10;
	info.x1 = CaptureTool::inst().GetValueFromImg(4, line);
	info.y1 = CaptureTool::inst().GetValueFromImg(5, line);
}
bool GameInfo::ObtainPlayerHp() {
	// 获得当前玩家血量
	player_info->player_hp = CaptureTool::inst().GetValueFromImg(1, 1);
	player_info->player_hp_max = CaptureTool::inst().GetValueFromImg(2, 1);
	if (last_loop_in_battle != in_battle && in_battle == 1) {
		time_begin_battle = GetTickCount();
	}
	last_loop_in_battle = in_battle;
	const DWORD now = GetTickCount();
	if (last_loop_player_hp > player_info->player_hp) {
		dq_lost_hp.push_back({ last_loop_player_hp - player_info->player_hp , now });
		if (dq_lost_hp.size() > 50) {
			dq_lost_hp.pop_front();
		}
	}
	if (in_battle == 1) {
		// 计算平均掉血
		if (dq_lost_hp.size() > 0) {
			int total_lost = 0;
			for (auto & it = dq_lost_hp.rbegin(); it != dq_lost_hp.rend(); it++) {
				auto & item = *it;
				if (now - item.time <= 5000) {
					total_lost += item.lost_value;
				}
				else {
					break;
				}
			}
			auto & front = dq_lost_hp.front();
			SetElapseTime((now - time_begin_battle) / 1000.0f);
			SetLostHP_InFiveSecond(total_lost);
		}
	}
	else {
		time_begin_battle = 0;
		dq_lost_hp.clear();
		SetElapseTime(0.0f);
		SetLostHP_InFiveSecond(0.0f);
	}
	last_loop_player_hp = player_info->player_hp;
	if (player_info->player_hp >= 0 && player_info->player_hp_max > 0 && player_info->player_hp_max >= player_info->player_hp) {
	}
	else {
		return false;
	}
	return true;
}

ActionSt & GameInfo::GetActionByIndex(int index) {
	return vec_action_[index];
}

ActionSt & GameInfo::GetActionByKeyIndex(int key_index)
{
	for (auto& action : vec_action_)
	{
		if (action.key_index == key_index)
		{
			return action;
		}
	}
	throw std::exception("no key index");
}

ActionSt & GameInfo::GetActionBySpellId(int spell_id) {
	return map_action_[spell_id];
}

ActionSt * GameInfo::GetActionPtrBySpellId(int spell_id) {
	auto it = map_action_.find(spell_id);
	if (it != map_action_.end()) {
		auto & ret = it->second;
		return &ret;
	}
	return NULL;
}

bool GameInfo::IsActionNotCDAndInRange(int spell_id) {
	auto it = map_action_.find(spell_id);
	if (it != map_action_.end()) {
		return (it->second.cool_down == 0 && it->second.in_range == 1);
	}
	return false;
}

bool GameInfo::SpellCostManaCheck(int spell_id)
{
	bool can_use = true;
	auto st_cost_mana = GetSpellCostMana((SpellID)spell_id);
	ASSERT(st_cost_mana.power_type != -1);
	int cost_mana = st_cost_mana.cost_mana;
	SpellID spell_free = GetSpellFreeBuff((SpellID)spell_id);
	if (spell_free != SpellID_None && player_info->buff(spell_free).Up())
	{
		cost_mana = 0;
	}
	int comp_mana = player_mana;
	if (comp_mana < cost_mana)
	{
		can_use = false;
	}
	return can_use;
}

bool GameInfo::CheckSpellCanUse(int spell_id)
{
	bool can_use = true;
	// 
	if (!IsActionNotCDAndInRange(spell_id))
	{
		can_use = false;
	}
	auto st_cost_mana = GetSpellCostMana((SpellID)spell_id);
	ASSERT(st_cost_mana.power_type != -1);
	int cost_mana = st_cost_mana.cost_mana;
	SpellID spell_free = GetSpellFreeBuff((SpellID)spell_id);
	if (spell_free != SpellID_None && player_info->buff(spell_free).Up())
	{
		cost_mana = 0;
	}
	int comp_mana = player_mana;
	if (st_cost_mana.power_type != mana_power_type)
	{
		if (st_cost_mana.power_type == power_type)
		{
			comp_mana = power_cur;
		}
	}
	if (comp_mana < cost_mana)
	{
		can_use = false;
	}
	return can_use;
}

double GameInfo::GetActionChargeFraction(int spell_id) {
	auto it = map_action_.find(spell_id);
	if (it != map_action_.end()) {
		auto & action = it->second;
		auto fraction = action.spell_charge_left / 100.0f;
		fraction = fraction + action.spell_charge_curr;
		return fraction;
	}
	return 0.0f;
}

int GameInfo::GetActionCDBySpellId(int spell_id) {
	auto it = map_action_.find(spell_id);
	if (it != map_action_.end()) {
		return it->second.cool_down;
	}
	return -1;
}

SpellConfig & GameInfo::GetSpellConfigBySpellID(int spell_id) {
	SpellConfig & ret = map_spell_config_[spell_id];
	if ((ret.name_cn == "" || ret.name_en == "") && spell_id != 0) {
		// 需要保存记录,并且进行查找
		ret.spell_id = spell_id;
		DbTool::inst().InsertEmptySpellConfig(ret);
		ret.name_cn = "未知法术";
		ret.name_en = "UnknowName";
		ret.need_gcd = true;
	}
	return ret;
}

BuffOrDebuff & GameInfo::GetPlayerBuff(int index) {
	return player_info->buffs[index];
}

BuffOrDebuff & GameInfo::GetTargetDebuff(int index) {
	return target_info->debuffs[index];
}

RuneInfo & GameInfo::GetRune(int index) {
	return vec_rune_[index];
}

int GameInfo::GetTargetDebuffCD(int debuff_spell_id) {
	int ret = -1;

	auto it = target_info->map_debuff_.find(debuff_spell_id);
	if (it != target_info->map_debuff_.end()) {
		auto & buff = it->second;
		return buff.duration;
	}
	return ret;
}

int GameInfo::GetTargetDebuffStack(int spell_id) {
	int ret = -1;
	auto it = target_info->map_debuff_.find(spell_id);
	if (it != target_info->map_debuff_.end()) {
		auto & buff = it->second;
		return buff.stack;
	}
	return ret;
}

int GameInfo::GetPlayerBuffUp(int buff_spell_id) {
	int ret = -1;

	auto it = player_info->map_buff_.find(buff_spell_id);
	if (it != player_info->map_buff_.end()) {
		auto & buff = it->second;
		return 1;
	}
	return 0;
}

int GameInfo::GetPlayerBuffRemainTime(int buff_spell_id) {
	int ret = -1;
	auto it = player_info->map_buff_.find(buff_spell_id);
	if (it != player_info->map_buff_.end()) {
		auto & buff = it->second;
		return buff.duration;
	}
	return ret;
}

int GameInfo::GetPlayerBuffStack(int spell_id) {
	int ret = -1;
	auto it = player_info->map_buff_.find(spell_id);
	if (it != player_info->map_buff_.end()) {
		auto & buff = it->second;
		return buff.stack;
	}
	return ret;
}

size_t GameInfo::GetPlayerBuffCount() const {
	return player_info->buffs.size();
}


size_t GameInfo::GetTargetDebuffCount() const {
	return target_info->debuffs.size();
}


bool GameInfo::PlayerInBattle() {
	return in_battle == 1;
}

bool GameInfo::TargetIsEnemy() {
	return target_is_enemy == 1;
}

int GameInfo::GetTargetHp() const {
	return target_info->player_hp;
}

void GameInfo::SetTargetHp(int val) {
	target_info->player_hp = val;
}

bool GameInfo::HasOpenPetUI() {
	return has_pet_ui == 1;
}

int GameInfo::GetPetHp() const {
	return pet_hp;
}

void GameInfo::SetPetHp(int val) {
	pet_hp = val;
}

int GameInfo::GetPlayerMana() const {
	return player_mana;
}

void GameInfo::SetPlayerMana(int val) {
	player_mana = val;
}

int GameInfo::GetRunicPowerDeficit() {
	return player_mana_max - player_mana;
}

// int GameInfo::GetPlayerHpMax() const {
// 	return player_info->player_hp_max;
// }
// 
// void GameInfo::SetPlayerHpMax(int val) {
// 	player_info->player_hp_max = val;
// }
// 
// int GameInfo::GetPlayerHp() const {
// 	return player_info->player_hp;
// }
// 
// void GameInfo::SetPlayerHp(int val) {
// 	player_info->player_hp = val;
// }
// 
// double GameInfo::GetPlayerHpPercent()
// {
// 	return GameInfo::inst().GetPlayerHp()*1.0f / GameInfo::inst().GetPlayerHpMax();
// }

int GameInfo::GetRuneReadyCount() const {
	return runeReadyCount;
}

void GameInfo::SetRuneReadyCount(int val) {
	runeReadyCount = val;
}

int GameInfo::GetPlayerClass() const {
	return player_class;
}

void GameInfo::SetPlayerClass(int val) {
	player_class = val;
}


using MapClassName = std::map<PlayerClass, CString>;
MapClassName map_class_map = {
	{ Warrior,L"Warrior"},
	{ Paladin,L"Paladin" },
	{ Hunter,L"Hunter" },
	{ Rogue,L"Rogue " },
	{ Priest,L"Priest" },
	{ DeathKnight,L"DeathKnight" },
	{ Shaman,L"Shaman" },
	{ Mage,L"Mage" },
	{ Warlock,L"Warlock" },
	{ Monk,L"Monk" },
	{ Druid,L"Druid" },
	{ Demon_Hunter,L"Demon_Hunter" },
};

CString & GameInfo::GetPlayerClassName() {
	return map_class_map[(PlayerClass)player_class];
}

int GameInfo::GetPlayerManaMax() const {
	return player_mana_max;
}

void GameInfo::SetPlayerManaMax(int val) {
	player_mana_max = val;
}

int GameInfo::GetFormID()
{
	return nFormID;
}

int GameInfo::GetTargetHpMax() const {
	return target_info->player_hp_max;
}

void GameInfo::SetTargetHpMax(int val) {
	target_info->player_hp_max = val;
}

int GameInfo::GetGlobalCDExecute() {
	return 13;
}

int GameInfo::GetGlobalCD() const {
	return gcd_;
}

void GameInfo::SetGlobalCD(int val) {
	gcd_ = val;
}

int GameInfo::GetTargetSpellCanInterupt() const {
	return target_spell_can_interupt;
}

void GameInfo::SetTargetSpellCanInterupt(int val) {
	target_spell_can_interupt = val;
}

void GameInfo::SetPartyInfo(int inParty, int PartyNum) {
	in_party = inParty;
	party_num = PartyNum;
}

void GameInfo::SetRaidInfo(int inRaid, int RaidNum) {
	in_raid = inRaid;
	raid_num = raid_num;
}

bool GameInfo::IsInParty() {
	return in_party > 0;
}

bool GameInfo::IsInRaid() {
	return in_raid > 0;
}

int GameInfo::GetPartyNum() {
	return party_num;
}

int GameInfo::GetRaidNum() {
	return raid_num;
}

double GameInfo::GetLostHP_InFiveSecond() const {
	return total_lost_;
}

void GameInfo::SetLostHP_InFiveSecond(double val) {
	total_lost_ = val;
}

double GameInfo::GetElapseTime() const {
	return elapse_time;
}

void GameInfo::SetElapseTime(double val) {
	elapse_time = val;
}

int GameInfo::GetPlayerSpec() const {
	return player_spec;
}

void GameInfo::SetPlayerSpec(int val) {
	player_spec = val;
}

int GameInfo::GetPlayerSpecializationID() const {
	return player_specialization_id;
}

void GameInfo::SetPlayerSpecializationID(int val) {
	player_specialization_id = val;
}

int GameInfo::RuneTimeTo(int rune_count) {
	std::vector<int> vec_time;
	int ready_count = 0;
	for (int i = 1; i < 6; i++) {
		const auto & rune = vec_rune_[i];
		if (rune.rune_rest_time == 0) {
			ready_count++;
		}
		else {
			vec_time.push_back(rune.rune_rest_time);
		}
	}
	if (ready_count >= rune_count) {
		return 0;
	}
	else {
		std::sort(vec_time.begin(), vec_time.end());
		int extra_count = rune_count - ready_count;
		return vec_time[extra_count - 1];
	}
	return 99;
}

bool GameInfo::IsTarget(std::string heal_target)
{
	if (heal_target == "target")
	{
		return true;
	}
	else if (heal_target == "player")
	{
		return GetIsPlayerIsTarget();
	}
	if (this->in_raid > 0)
	{
		auto pos = heal_target.find("raid");
		if (pos != std::string::npos)
		{
			std::string number = heal_target.substr(pos);
			int n = atoi(number.c_str());
			if (IsTarget_Team_Raid(n))
			{
				return true;
			}
		}
	}
	else if (this->in_party > 0)
	{
		auto pos = heal_target.find("party");
		if (pos != std::string::npos)
		{
			std::string number = heal_target.substr(pos);
			int n = atoi(number.c_str());
			if (IsTarget_Team_Raid(n))
			{
				return true;
			}
		}
	}
	return false;
}

bool GameInfo::IsTarget_Team_Raid(int n)
{
	if (vec_team_and_raid_.size() > n)
	{
		auto& item = vec_team_and_raid_[n];
		if (item->UnitIsTarget > 0)
		{
			return true;
		}
	}
	return false;
}

size_t GameInfo::GetTeam_Raid_Count()
{
	return vec_team_and_raid_.size();
}

bool GameInfo::IsPlayer_Channel_or_Casting()
{
	return player_is_channel == 1 || player_is_casting == 1;
}

int GameInfo::GetPlayerExpectHealValue()
{
	return player_info->GetExpectHealValue();
}

int GameInfo::GetTargetExpectHealValue()
{
	return target_info->GetExpectHealValue();
}

Team_Raid_Info& GameInfo::GetTarget()
{
	return *target_info;
}

Team_Raid_Info& GameInfo::GetPlayer()
{
	return *player_info;
}

Team_Raid_Info* GameInfo::SpellByPlayer(SpellID spell_id)
{
	if (player_info->buff(spell_id).cast_by_player == 1)
	{
		return player_info.get();
	}
	if (target_info->buff(spell_id).cast_by_player == 1)
	{
		return target_info.get();
	}
	for (auto& ptr : vec_team_and_raid_)
	{
		if (ptr&& ptr->buff(spell_id).cast_by_player == 1)
		{
			return ptr.get();
		}
	}
	return nullptr;
}

RoutineConfig& GameInfo::GetRoutineConfig()
{
	return  routine_config;
}

